package cn.initcap.algorithm.leetcode;

import java.math.BigDecimal;

/**
 * （米勒投影）算法 将地球经纬度转换为平面坐标
 *
 * @author initcap
 * @date Created in 2019/12/31 17:05.
 */
public class MillierConvertion {
    private static final BigDecimal DIVIDE = new BigDecimal(2500);

    public static void main(String[] args) {
        // 天津转换 translate(1413.88 619.56)
        BigDecimal[] tianjin = MillierConvertion(39.13, 117.19);
        // 上海转换 translate(1528.88 874.56)
        BigDecimal[] shanghai = MillierConvertion(31.23, 121.47);
        double tianjinXval = tianjin[0].divide(DIVIDE).setScale(2, BigDecimal.ROUND_HALF_DOWN).doubleValue();
        double tianjinYval = tianjin[1].divide(DIVIDE).setScale(2, BigDecimal.ROUND_HALF_DOWN).doubleValue();
        double shanghaiXval = shanghai[0].divide(DIVIDE).setScale(2, BigDecimal.ROUND_HALF_DOWN).doubleValue();
        double shanghaiYval = shanghai[1].divide(DIVIDE).setScale(2, BigDecimal.ROUND_HALF_DOWN).doubleValue();
        double div = 1.07;
        System.out.println(String.format("天津市市辖区和平区劝业场街道转换后的{ x : %s, y: %s }", tianjinXval / div - 11000, tianjinYval / div - 1955));
        System.out.println(String.format("上海市市辖区黄浦区南京东路街道转换后的{ x : %s, y: %s }", shanghaiXval / div - 11000, shanghaiYval / div - 1955));
    }

    /**
     * @param lat 纬度，南纬是负数
     * @param lon 经度，西经为负数
     * @return [x, y]
     */
    public static BigDecimal[] MillierConvertion(double lat, double lon) {
        //地球周长
        double L = 6381372 * Math.PI * 2;
        // 平面展开后，x轴等于周长
        double W = L;
        // y轴约等于周长一半
        double H = L / 2;
        // 米勒投影中的一个常数，范围大约在正负2.3之间
        double mill = 2.3;
        // 将经度从度数转换为弧度
        double x = lon * Math.PI / 180;
        // 将纬度从度数转换为弧度
        double y = lat * Math.PI / 180;
        // 米勒投影的转换
        y = 1.25 * Math.log(Math.tan(0.25 * Math.PI + 0.4 * y));
        // 弧度转为实际距离
        BigDecimal xr = new BigDecimal((W / 2) + (W / (2 * Math.PI)) * x);
        BigDecimal yr = new BigDecimal((H / 2) - (H / (2 * mill)) * y);
        BigDecimal[] result = new BigDecimal[2];
        result[0] = xr;
        result[1] = yr;
        return result;
    }

}
